/*
frigOS
Licensed under GPLv3

This file contains defintitions for using the two serial ports
found on the AtMega128 family of processors.

USART0 is assumed to be connected to the Bioloid's AX-12 motors
(see ax12motor.h), and is half-duplex.

USART1 is assumed to be connected to a PC and is full-duplex.
*/

#ifndef __SERIAL_H__
#define __SERIAL_H__

#include "defs.h"
#include "kernel.h"

#include <avr/io.h>

// TODO: unnecessary once code rewrites are complete
extern uint8_t reply_status;
extern uint8_t reply_valid;
enum ReplyStatus
{

    REPLY_OFF,
    REPLY_ON
};
static inline uint8_t getReplyStatus(void)
{
    return reply_status;
};

static inline void setReplyStatus(uint8_t status)
{
    reply_status = status;
};
// END TODO

// what serial port should an IO_Queue transmit on?
enum TransmitOnSerialPort
{
    TX_ON_NONE,     // queue is receive-only
    TX_ON_USART0,   // queue sends over USART0
    TX_ON_USART1    // queue sends over USART1
};

// circular queue used by Rx and Tx interrupts to buffer the I/O
// data should be inserted and extracted by the enqueue and dequeue
// functions below
typedef struct io_queue
{
    uint8_t maxLength;          // the maximum length of the queue
    uint8_t queueLength;        // the current number of bytes in the queue
    volatile uint8_t* buffer;   // pointer to an array of length maxLength
    volatile uint8_t in;        // the index of back of the queue
    volatile uint8_t out;       // the index of the front of the queue
    volatile BOOL empty;        // is the queue empty right now?
    volatile BOOL full;         // is the queue full right now?
    volatile BOOL txOnEnqueue;  // next time we enqueue a byte do we need to synthetically fire a Tx interrupt to restart the interrupt-driven I/O?
    volatile uint8_t txOn;      // what serial port does this queue transmit over?
} IO_Queue;


// add a byte to the back of a queue
void enqueue(uint8_t data, volatile IO_Queue *queue);

// remove a byte from the front of the queue
uint8_t dequeue(volatile IO_Queue *queue);


// automagically include USART0/1 headers if serial.h is included
#include "usart0.h"
#include "usart1.h"

// initialize the RS485 on the CM-5 board
// this is required in order to use USART0 to talk to
// the dynamizel components
void initRS485(void);

// convert the low-4 nibble of a byte into its corresponding hex digit
char nibble2char(uint8_t nibble);

// convert a single byte into a hex string (no null terminator)
// store the result in dest.  dest MUST be 2 bytes or longer
void byte2hex(uint8_t src, char dest[]);

#endif  //__SERIAL_H__
